<?php 
namespace App\GameService\games;
use App\Utility\BaseEnum;
use App\Common\AuthCommon;
use Swoole\Timer;
use App\GameService\games;
use App\Common\BaseComm;
use App\Common\PlayCommon;
use App\Utility\RedisTools;
use App\Enum\SysEnum;
use App\Common\GameCommon;
use EasySwoole\EasySwoole\Task\TaskManager;
use App\Enum\CardEnum;

/**
 * 游戏互动基类
 */
class BasePlay
{
    public $baseOneTimer = 0;
    public $loopTimerStop = FALSE;
    public $baseTimeLong = FALSE;
    public $baseGameName = FALSE;
    public $gameStatus = FALSE ;
    public $gtimeConfig = FALSE;    //配置游戏时间配置
    
    //开始游戏入口 public abstract function asycStartGame();    
    
    /**
     * TODO 获取当前游戏配置的时间
     * @param string $pubkey 配置键
     * @return int  时间秒
     */
    public function getConfigTimeLong($pubkey):int 
    {
        if (!$this->gtimeConfig) {
            return FALSE;
        }
        $timeLong = $this->gtimeConfig[$pubkey] ?? 0;
        return $timeLong;
    }
    
    //设置名称
    public function setGameName($gameName){
        $this->baseGameName = $gameName; ;
    }
    
    //设置游戏状态；
    public function setGameStatus($status){
        $this-> gameStatus = $status;
    }
    
    //设置定时临时停止
    public function setLoopTimerStop() {
        return $this->loopTimerStop = true; //紧急停掉标识
    }
    
    /**
     * 通用定时器倒计时功能
     * @param int $sleepTime        休息时间长
     * @param array $Params         传入参数
     * @param array $callBackFun    回调函数执行
     */
    public function asycTimeStart($sleepTime,$gameNo , $Params = FALSE,$callBackFun = FALSE){
        $this->baseTimeLong = $sleepTime;
        
        if(isset($this->baseOneTimer) && intval($this->baseOneTimer) > 0){
            BaseEnum::Logger("定时器销毁：Timer-{$this->baseOneTimer} ,新开倒计时 总共[{$sleepTime}] 秒.....>请等待：" . json_encode($Params), 'user-login');          //推送倒计时显示数
            //Timer::clear($this->baseOneTimer); //定时器
        }
        $oneStatus = isset($Params["status"]) ? $Params["status"] : "";
        $allFds = isset($Params["clientIds"]) ? $Params["clientIds"] : FALSE;
        $stepIndex = (isset($Params["step"]) && intval($Params["step"]) >= 1) ? intval($Params["step"]) : 0;
        $waitSiteNo = (isset($Params["waitSiteNo"]) && intval($Params["waitSiteNo"]) >= 0) ? intval($Params["waitSiteNo"]) : FALSE;
        $gameLun = (isset($Params["gameLun"]) && intval($Params["gameLun"]) >= 1) ? intval($Params["gameLun"]) : 1;
        
        $pushList = ["leftTime" => $sleepTime];
        if($waitSiteNo !== FALSE) {
            $pushList["gLun"] = $gameLun;
            $pushList["waitNo"] = $waitSiteNo;
        }else{
            $pushList["room_status"] = $oneStatus;
        }
        if($stepIndex > 0){
            $pushList["step"] = $stepIndex;
        }
        $pushList["flag"] = TRUE;
        
        //倒计时的内容放在内存变量中
        PlayHelp::getInstance()->setLoopTim($gameNo,$sleepTime);
        $pushRes = array('m'=> BaseEnum::XYM_0X10 ,"data"=> $pushList);
        AuthCommon::pushFrontWeb($allFds,json_encode($pushRes,JSON_UNESCAPED_UNICODE,JSON_UNESCAPED_SLASHES)) ; //推送
        
        //TODO 启用定时器；推送倒计时给前端
        $this->baseOneTimer = Timer::tick(1000, function() use ($gameNo,$allFds,$pushList,$callBackFun, $sleepTime){
            $myVal = PlayHelp::getInstance()->getLoopTim($gameNo);
            $realTime = $myVal = $myVal - 1;
            PlayHelp::getInstance()->setLoopTim($gameNo,$myVal);                                    //  保存修改后的值
            $loopTimerStop = PlayHelp::getInstance()->getCommTimerStop($gameNo);                    //  停掉定时器（2秒以上）
            $ifStop = ($sleepTime >0 && $loopTimerStop === TRUE && $sleepTime - $myVal >= 2) ? TRUE : FALSE;
            if (intval($myVal) <= 0 || $ifStop === true) {                                          // 特殊情况中断倒计时数据； 
                Timer::clear($this->baseOneTimer);
                $myVal = 0;
                $this->baseOneTimer = null;
                PlayHelp::getInstance()->setCommTimerStop($gameNo,FALSE);           //unset(Games::$gameCommonTimer[$gameNo]);    //清空数据
                BaseEnum::Logger("定时器工作结束：(clear)-倒计时结束执行功能： [leftTime={$myVal},realLeftTime={$realTime}]--->>>>loop_hand={$loopTimerStop}----->". $gameNo, 'user-login');
                //TODO 最后一次推送
                $pushList["flag"] =  FALSE;
                $pushList["leftTime"] = 0 ; //所有都清为0才操作
                $pushRes2 = array('m'=> BaseEnum::XYM_0X10 ,"data"=> $pushList);
                TaskManager::getInstance()->async(function()use($allFds,$pushRes2){
                    AuthCommon::pushFrontWeb($allFds,BaseEnum::JsonEncode($pushRes2)) ;             //推送
                });
                if($callBackFun !== FALSE){ 
                    @call_user_func($callBackFun);  //回调方案
                }                        
            }
            //TODO 推给前端用户
            if(!empty($allFds) && $myVal > 0){
                if (isset($myVal) && $myVal < $sleepTime) { $pushList["flag"] =  FALSE; }
                $pushList["leftTime"] = $myVal ;
                $pushRes = array('m'=> BaseEnum::XYM_0X10 ,"data"=> $pushList);
                AuthCommon::pushFrontWeb($allFds,BaseEnum::JsonEncode($pushRes)) ; //推送
            }
        });
    }
    
    //TODO 机器人自动抢庄最高倍数庄
    public function startRobotDoQiangz($gameId,$gameNo,$allRobotUsers = FALSE,$allClientFds = FALSE){
        if(!$allRobotUsers || !$allClientFds){
            $allRobotUsers=PlayCommon::getGameRobotsUser($gameId,$gameNo,$allClientFds);
        } 
        $robot_num = !empty($allRobotUsers) ? sizeof($allRobotUsers) : 0;
        BaseEnum::Logger("机器人抢庄：GameId-{$gameId} ,当前局[{$gameNo}] 共有{$robot_num}个机器人>" . json_encode($allRobotUsers), 'user-login');          //推送倒计时显示数
        
        //TODO 机器人列表(数据处理)
        if (!empty($allRobotUsers) && $robot_num > 0) {
            switch ($gameId){
                case 101:
                    $sleepTime = rand(3,4);
                    break;
                case 103:
                    $sleepTime = rand(2,3);
                    break;
                default:
                    $sleepTime = rand(3,4);
                    break;
            }
            //TODO 启动抢庄
            Timer::after($sleepTime * 1000, function() use($gameId,$gameNo,$allRobotUsers,$allClientFds) {
                $pushMsg = [];
                $rediskey = SysEnum::ONLINE_BDATA_KEY;
                if(!$allRobotUsers || !$gameNo || !$allClientFds) return false;
                $qzStr = RedisTools::Pool_hGet($rediskey, $gameNo);
                $qzList = !empty($qzStr) ? json_decode($qzStr,TRUE) :[];
                foreach ($allRobotUsers as $obj){
                    $curUfd = $obj['fd'] ?? 0;
                    $seatIndex = $obj['seatNo'] ?? 0;
                    switch ($gameId){
                        case 101:
                            $betMutl = rand(1,3);
                            break;
                        case 103:
                            $betMutl = rand(0,1);//三公随机抢庄
                            break;
                        default:
                            $betMutl = rand(1,3);
                            break;
                    }
                    if($seatIndex >= 0 && isset($obj['uid']) && $curUfd > 0){
                        $qzList[$seatIndex] = $betMutl ;             //抢庄倍数存起放在内存中
                        $pushMsg[] = ["seatNo" => $seatIndex, "mutdotts" => $betMutl, "p_fd" => $curUfd ];
                    }
                }
                if (!empty($pushMsg)) {
                    RedisTools::Pool_hSet($rediskey, $gameNo, BaseEnum::JsonEncode($qzList));   //TODO 抢庄倍数据存起来
                    TaskManager::getInstance()->async(function() use ($pushMsg,$allClientFds){
                        foreach ($pushMsg as $onedata){
                            @usleep( 800 * 1000);//0.5秒推送一次
                            $onePush = ["m"=> BaseEnum::XYM_0X18 , "data"=> $onedata];
                            AuthCommon::pushFrontWeb($allClientFds,json_encode($onePush));  //推送出去(默认不抢)
                        }
                    });
                    
                    //TODO 判断是否所有玩家都操作完(结束定时器)
                    GameCommon::stopQiangZhuang(sizeof($allClientFds), $gameNo,$qzList,0);
                }
            });
        }
    }

    
    //TODO 机器人自动下注
    public function startRobotDoBets($gameId,$gameRid,$gameNo,$maxBet=3) {
        //TODO 机器人列表下注操作(下注最低倍数)
        $allRobotUsers=PlayCommon::getGameRobotsUser($gameRid,$gameNo);
        $robot_num = !empty($allRobotUsers) ? sizeof($allRobotUsers) : 0;
        BaseEnum::Logger("机器人下注：GameId-{$gameRid} ,当前局[{$gameNo}] 共有{$robot_num}个机器人>" . json_encode($allRobotUsers), 'user-login');          //推送倒计时显示数
        
        //TODO 机器人列表(数据处理)
        if (!empty($allRobotUsers) && $robot_num > 0) {
            switch($gameId){
                case 103:
                    $sleepTime = rand(1,3);
                    break;
                default:
                    $sleepTime = rand(2,3); //TODO 启动 下注操作 ===> 下注最低倍数
                    $maxBet = 3;
                break;
            }
            Timer::after($sleepTime * 1000, function() use($gameId,$gameNo,$allRobotUsers,$maxBet) {
                $pushMsg = [];  //下注操作
                $gameDetail = BaseComm::distMemoryRooms($gameNo,FALSE);
                $allBets = $gameDetail['bets'] ?? FALSE;  //下注数据
                $allPlayer = $gameDetail['lists'] ?? FALSE;
                $gameStatus = $gameDetail['fjStatus'] ?? 0;
                $allClientFds = !empty($allPlayer) ? array_column($allPlayer, "fd","seatNo") : FALSE;
                //所有玩家都推送
                if(!$allRobotUsers || !$gameNo || !$gameDetail || !$allClientFds) return false;
                //TODO 订单只有未修改状态时才能下注
                if (isset($gameStatus) && intval($gameStatus) !== CardEnum::GAME_STEP_2) {
                    foreach ($allRobotUsers as $obj){
                        $betMutl = rand(1,$maxBet);           //每个机器人都下注随机倍数
                        $curUfd = $obj['fd'] ?? 0;
                        $seatIndex = $obj['seatNo'] ?? 0;
                        $isMain = isset($obj['mainflag']) ? intval($obj['mainflag']) : 0;
                        if($seatIndex >= 0 && isset($obj['uid']) && $curUfd > 0 && $isMain !== 1){
                            $allBets[$seatIndex] = $betMutl ;               //下注倍数存起放在内存中
                            $pushMsg[] = ["seatNo" => $seatIndex, "mutdotts" => $betMutl, "p_fd" => $curUfd ];
                        }
                    }
                    BaseEnum::Logger("机器人下注列表：GameNo-[{$gameNo}]  推送数据 >> " . json_encode($pushMsg), 'user-login');
                    if (!empty($pushMsg)) {
                        $gameDetail['bets'] = $allBets;
                        BaseComm::distMemoryRooms($gameNo,TRUE,$gameDetail);                        //TODO 下注数据存起来
                        foreach ($pushMsg as $onedata){
                            @usleep(600*1000);
                            $onePush = ["m"=> BaseEnum::XYM_0X19 , "data"=> $onedata];
                            AuthCommon::pushFrontWeb($allClientFds,json_encode($onePush));          //TODO 推送出去
                        }
                        GameCommon::stopQiangZhuang(sizeof($allClientFds), $gameNo,$allBets , 1);   //TODO 判断是否所有玩家都操作完(结束定时器)
                    }
                }
            });
        }
        return FALSE;
    }

}

?>